using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Dimok.Data.Database;
using Dimok.Data.DataSources;
using Dimok.Web.UI;
using GSP = gudusoft.gsqlparser;
namespace Dimok.Web.UI {

	#region Event Classes
	public delegate void GridViewDataSourceSelectedEventHandler(object sender,GridViewDataSourceSelectedEventArgs e);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Additional information for grid view data source selected events. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class GridViewDataSourceSelectedEventArgs :GridViewSelectEventArgs {
		public DataRow DataRow;
		public DataRow[] DataRows;
		public DataView DSView;
		public int RowIndex;
		public GridViewDataSourceSelectedEventArgs(DataRow[] dataRows,int newSelectedIndex,DataView dsView, int rowIndex)
			: base(newSelectedIndex) {
			DataRows = dataRows;
			DataRow = dataRows.Length > 0 ? dataRows[0] : null;
			DSView = dsView;
			RowIndex = newSelectedIndex >= 0 ? rowIndex : -1;
		}
	}
	public delegate void GridViewDataSourceSelectingEventHandler(object sender,GridViewDataSourceSelectingEventArgs e);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Additional information for grid view data source selecting events. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class GridViewDataSourceSelectingEventArgs :ObjectDataSourceSelectingEventArgs {
		public GridViewDataSourceSelectingEventArgs(ObjectDataSourceSelectingEventArgs e):
			base(e.InputParameters,e.Arguments,e.ExecutingSelectCount){}
	}
	public delegate void GridViewExEventHandler(object sender,GridViewExEventArgs e);

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Additional information for grid view ex events. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class GridViewExEventArgs :CancelEventArgs {
		public IOrderedDictionary Key;
		public IOrderedDictionary Values;
		public int RowIndex;
		public bool InEdit;
		public GridViewExEventArgs(IOrderedDictionary key,IOrderedDictionary values,int rowIndex)
			: this(key,values,rowIndex,false) {
		}
		public GridViewExEventArgs(IOrderedDictionary key, IOrderedDictionary values,int rowIndex,bool inEdit) {
			Key = key;
			Values = values;
			RowIndex = rowIndex;
			InEdit = inEdit;
		}
	}
	public delegate void SearchChangedEventHandler(string search);
	#endregion

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Table control. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public abstract class TableControl :UI.UserControlEx,ITableControl {

		#region Properties

		#region ConnectionString
		private string _connectionString;
		// PROPERTY:: ConnectionString

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the connection string. </summary>
		///
		/// <value>	The connection string. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Category("Database")]
		[Description("Connection string to database")]
		[DefaultValue("")]
		public string ConnectionString { get { return _connectionString; } set { _connectionString = value; } }
		#endregion

		// PROPERTY:: ViewName
		string _hideColumns = "";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the hide columns. </summary>
		///
		/// <value>	The hide columns. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Category("Database")]
		[Description("List of columns to hide")]
		[DefaultValue("")]
		public string HideColumns { get { return _hideColumns; } set { _hideColumns = value; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether the requires data binding. </summary>
		///
		/// <value>	true if requires data binding, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public bool RequiresDataBinding { get { return GV.RequiresDataBinding; } set { GV.RequiresDataBinding = value; } }

		private object _showHeader;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether the header is shown. </summary>
		///
		/// <value>	true if show header, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool ShowHeader { get { return (bool)_showHeader; } set { _showHeader = value; } }

		private object _showFooter;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether the footer is shown. </summary>
		///
		/// <value>	true if show footer, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool ShowFooter { get { return (bool)_showFooter; } set { _showFooter = value; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a value indicating whether the footer is set is shown. </summary>
		///
		/// <value>	true if show footer is set, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public bool ShowFooterIsSet { get { return _showFooter != null; } }

		private object _showSearch;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether the search is shown. </summary>
		///
		/// <value>	true if show search, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool ShowSearch { get { return (bool)_showSearch; } set { _showSearch = value; } }

		private object _showDelete;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether the delete is shown. </summary>
		///
		/// <value>	true if show delete, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool ShowDelete { get { return (bool)_showDelete; } set { _showDelete = value; } }

		private object _allowEdit;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether we allow edit. </summary>
		///
		/// <value>	true if allow edit, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool AllowEdit { get { return (bool)_allowEdit; } set { _allowEdit = value; } }

		private object _emptyRowPolicy = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the empty row policy. </summary>
		///
		/// <value>	The empty row policy. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public EmptyRowPolicyType EmptyRowPolicy { get { return (EmptyRowPolicyType)_emptyRowPolicy; } set { _emptyRowPolicy = value; } }
		
		private string _selectList = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a list of selects. </summary>
		///
		/// <value>	A List of selects. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string SelectList { get { return _selectList; } set { _selectList = value; } }

				private DataKey _selectedDataKey = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the selected data key. </summary>
		///
		/// <value>	The selected data key. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataKey SelectedDataKey { get { return _selectedDataKey; } set { _selectedDataKey = value; } }

		private DataRowView _selectedDataRowView = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the selected data row view. </summary>
		///
		/// <value>	The selected data row view. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public DataRowView SelectedDataRowView { get { return _selectedDataRowView; } set { _selectedDataRowView = value; } }

		private object _onSelectClick = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	JavaScript function to call when table row is selected. </summary>
		///
		/// <value>	The on select click. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public string OnSelectClick { get { return _onSelectClick+""; } set { _onSelectClick = value; } }

		private string _onRowClick = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	JavaScript function to call when table row is clicked. </summary>
		///
		/// <value>	The on row click. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public string OnRowClick { get { return _onRowClick; } set { _onRowClick = value; } }

		
		private string _filterDefault = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the filter default. </summary>
		///
		/// <value>	The filter default. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string FilterDefault { get { return _filterDefault; } 
			set { 
				_filterDefault = value;
				if (value != null) ObjectDS.FilterDefault = value;
			} 
		}

		private string _dsObjectType = "";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Full name for ObjectDataSource object which will be created dinamicaly. </summary>
		///
		/// <value>	The type of the ds object. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public string DSObjectType { get { return _dsObjectType; } set { _dsObjectType = value; } }

		private string _selectViewName = null;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	If DSObjectType is ObjectDataSourceBase it must be provided. </summary>
		///
		/// <value>	The name of the select view. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public string SelectViewName { get { return _selectViewName; } set { _selectViewName = value; } }


		private int _pageSize = -1;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the size of the page. </summary>
		///
		/// <value>	The size of the page. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public int PageSize { get { return _pageSize; } set { _pageSize = value; } }

		private bool _allowPaging = true;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets a value indicating whether we allow paging. </summary>
		///
		/// <value>	true if allow paging, false if not. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		[Bindable(true)]
		public bool AllowPaging { get { return _allowPaging; } set { _allowPaging = value; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Sets zero-based index of the edit. </summary>
		///
		/// <value>	The edit index. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public int EditIndex { set { GridViewEx.EditIndex = value; } }

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the selected index. </summary>
		///
		/// <value>	The selected index. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public int SelectedIndex { get { return GridViewEx.SelectedIndex; } set { GridViewEx.SelectedIndex = value; } }

		#region SqlDS
		private SqlDataSource _ds;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the sql ds. </summary>
		///
		/// <value>	The sql ds. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected SqlDataSource SqlDS { get { return _ds != null ? _ds : _ds = (SqlDataSource)Find.ChildByType(this,typeof(SqlDataSource)); } }
		private AObjectDataSourceBase _ods;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the object ds. </summary>
		///
		/// <value>	The object ds. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected AObjectDataSourceBase ObjectDS {
			get {
				try {
					EnsureDS(null, null);
					return _ods != null ? _ods : _ods = FindControl(GridViewEx != null ? GridViewEx.DataSourceID : DATA_SOURCE_ID) as AObjectDataSourceBase;
				} catch(Exception exc) { throw SmartException.GetControlTraceException(this,Config.UI.DebugMode,exc); }
			}
			set { _ods = value; }
		}
		private GridViewEx _grv;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the grid view ex. </summary>
		///
		/// <value>	The grid view ex. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public GridViewEx GridViewEx { 
			get { return _grv != null ? _grv : _grv = (GridViewEx)Find.ChildByType(GetType(),this,typeof(GridViewEx)); }
			set { _grv = value; }
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Adds a where. </summary>
		///
		/// <param name="where">	The where. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void AddWhere(string where) { ObjectDS.Where.Add(where); }

		#endregion

		#region Filter
		private const string VS_SELECT_FILTER = "SELECT_FILTER";
		private string _selectFilter = "";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets or sets the select filter. </summary>
		///
		/// <value>	The select filter. </value>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public virtual string SelectFilter {
			get { return _selectFilter; }
			set {
				EnsureChildControls();
				foreach(Control control in Controls)
					if(control.HasControls()) {
						Control grv = control.FindControl("grv");
						grv = null;
					}
				_selectFilter = value;
				SetSelectFilter();
			}
		}
		#endregion

		#endregion

		#region Methods

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Updates the parameters. </summary>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void UpdateParameters() { GridViewEx.UpdateParameters(); }
		#endregion

		#region Events
		[Description("Row Selected Event")]
		public event GridViewDataSourceSelectedEventHandler DataSourceSelected;
		public event GridViewDataSourceSelectingEventHandler DataSourceSelecting;
		public event GridViewExEventHandler RowSelected;
		public event EventHandler<GridViewInsertEventArgs> RowInserting;
		public event EventHandler<GridViewInsertEventArgs> RowInserted;
		public event GridViewDeletedEventHandler RowDeleted;
		public event GridViewDeleteEventHandler RowDeleting;
		public event EventHandler<GridViewExEditEventArgs> RowEditingEx;
		public event GridViewUpdatedEventHandler RowUpdated;
		public event EventHandler<GridViewUpdateEventArgs> RowUpdating;
		public event GridViewRowEventHandler RowCreated;
		public event GridViewPageEventHandler PageIndexChanging;
		public event SearchChangedEventHandler SearchChanged;
		
		#endregion

		#region Overrides

		#region State Control

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Override this method to add members that need to be persisted in Control's State. </summary>
		///
		/// <param name="values">	. </param>
		///
		/// <example>	values["SelectFilter"] = SelectFilter</example>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void GetStateValues(Hashtable values) {
			base.GetStateValues(values);
			values["DSObjectType"] = DSObjectType;
			values["SelectViewName"] = SelectViewName;
			values["SelectList"] = SelectList;
			values["FilterDefault"] = FilterDefault;
			values["OnRowClick"] = OnRowClick;
			values["OnSelectClick"] = OnSelectClick;
			//values["ShowSearch"] = _showSearch;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Override this method to get members that have been  persisted in Control's State. </summary>
		///
		/// <param name="values">	. </param>
		///
		/// <example>	SelectFilter = values["SelectFilter"] + ""</example>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void SetStateValues(Hashtable values) {
			base.GetStateValues(values);
			DSObjectType = values["DSObjectType"] as string;
			SelectViewName = values["SelectViewName"] as string;
			SelectList = values["SelectList"] == null ? null : values["SelectList"] + "";
			FilterDefault = values["FilterDefault"] as string;
			OnRowClick = values["OnRowClick"] == null ? null : values["OnRowClick"] + "";
			OnSelectClick = values["OnSelectClick"] == null ? null : values["OnSelectClick"] + "";
			//if (values["ShowSearch"] != null) _showSearch = (bool)values["ShowSearch"];
		}
		#endregion

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the initialise event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="e">	Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			Page.LoadComplete += new EventHandler(Page_LoadComplete);
			List<Control> dbConn = Find.ChildrenByType(this,typeof(SqlDataSource));
			foreach(Control c in dbConn)
				((SqlDataSource)c).ConnectionString = ConnectionString;
			GridViewEx.SelectedIndexChanged += new EventHandler(GridViewEx_SelectedIndexChanged);
			GridViewEx.PageIndexChanging += new GridViewPageEventHandler(GridViewEx_PageIndexChanging);
			GridViewEx.SearchChanged += new GridViewEx.SearchChangedEventHandler(GridViewEx_SearchChanged);
			GridViewEx.RowInserting += new EventHandler<GridViewInsertEventArgs>(OnRowInserting);
			GridViewEx.RowInserted += new EventHandler<GridViewInsertEventArgs>(OnRowInserted);
			GridViewEx.RowDeleted += new GridViewDeletedEventHandler(GridViewEx_RowDeleted);
			GridViewEx.RowDeleting += new GridViewDeleteEventHandler(GridViewEx_RowDeleting);
			GridViewEx.RowEditingEx += new EventHandler<GridViewExEditEventArgs>(GridViewEx_RowEditingEx);
			GridViewEx.RowUpdating += new EventHandler<GridViewUpdateEventArgs>(GridViewEx_RowUpdating);
			GridViewEx.RowUpdated += new GridViewUpdatedEventHandler(GridViewEx_RowUpdated);
			GridViewEx.RowCreated += new GridViewRowEventHandler(OnRowCreated);
			GridViewEx.EnableViewState = true;
			//GridViewEx.HideColumns = HideColumns;
			//SetSelectFilter();
			//if(SqlDS != null) GridViewEx.DataSourceID = SqlDS.ID;
		}

		#region EnsureDS
		public readonly string DATA_SOURCE_SUFFIX = "DataSource";
		const string DATA_SOURCE_ID = "ds";

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Loads the ds. </summary>
		///
		/// <param name="DSObjectType">	Type of the ds object. </param>
		/// <param name="dsSuffix">			The ds suffix. </param>
		///
		/// <returns>	The ds. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static AObjectDataSourceBase LoadDS(string DSObjectType, string dsSuffix) {
			Type t = Type.GetType(DSObjectType);
			if (t == null && !Regex.IsMatch(DSObjectType, dsSuffix + "$", RegexOptions.IgnoreCase))
				t = Type.GetType(DSObjectType + dsSuffix);
			if (t == null) throw new Exception(DSObjectType + " type can not be found in" + MethodBase.GetCurrentMethod().Module.Assembly.FullName);
			return Activator.CreateInstance(t) as AObjectDataSourceBase;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Initialises the ds. </summary>
		///
		/// <param name="dsBase">	The ds base. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void InitDS(AObjectDataSourceBase dsBase) {
			//dsBase.EmtyRowPolicy = EmptyRowPolicyType.OnlyIfEmpty;
			if (_emptyRowPolicy != null) dsBase.EmtyRowPolicy = EmptyRowPolicy;
			if (_selectList != null) dsBase.SelectList = SelectList;
			if (typeof(ATableDataSource).IsInstanceOfType(dsBase) && _selectViewName == null)
				throw new Exception("TableDataSource must have explicit SelectViewName");
			if (SelectViewName != null) dsBase.SelectViewName = SelectViewName;
			dsBase.ID = GridViewEx != null ? GridViewEx.DataSourceID : DATA_SOURCE_ID;
			Controls.Add(dsBase);
			ObjectDS = dsBase;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Ensures that ds. </summary>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void EnsureDS(object sender, EventArgs e) {
			if (_ods == null && DSObjectType != "")
				InitDS(LoadDS(DSObjectType, DATA_SOURCE_SUFFIX));
			if (FilterDefault != null && _ods != null && _ods.FilterDefault != FilterDefault)
				_ods.FilterDefault = FilterDefault;
		}
		#endregion

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the load event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="GetControlTraceException">	Thrown when getcontroltrace. </exception>
		///
		/// <param name="e">	Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnLoad(EventArgs e) {
			try {
				base.OnLoad(e);
				if (ObjectDS != null) {
					ObjectDS.Selected += new ObjectDataSourceStatusEventHandler(ObjectDS_Selected);
					ObjectDS.Selecting += new ObjectDataSourceSelectingEventHandler(ObjectDS_Selecting);
				}

				if (!Page.IsPostBack) {
					GridViewEx.DataBound += new EventHandler(GridViewEx_DataBound);
					if (_showDelete != null) GridViewEx.ShowDelete = ShowDelete;
					if (_allowEdit != null) GridViewEx.AllowEdit = AllowEdit;
					if (_showHeader != null) GridViewEx.ShowHeader = ShowHeader;
					GridViewEx.AllowPaging = AllowPaging;
					if (_showFooter != null) GridViewEx.ShowFooter = ShowFooter;
				} else {
					string buildFilter = GridViewEx.BuildFilter();
					if (buildFilter != "") SelectFilter = buildFilter;
				}

				if (_onRowClick != null) GridViewEx.OnRowClick = OnRowClick;
				if (_onSelectClick != null) GridViewEx.OnSelectClick = OnSelectClick;
				if (_showSearch != null) GridViewEx.ShowSearch = ShowSearch;
				SetSelectFilter();
			} catch (Exception exc) {
				throw SmartException.GetControlTraceException(this, Config.UI.DebugMode, exc);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by Page for load complete events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void Page_LoadComplete(object sender, EventArgs e) {
			//if (!Page.IsPostBack && PageSize > 0) {
			//  GridViewEx.PageSize = PageSize;
			//}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse t lz filter. </summary>
		///
		/// <param name="filter">	The filter. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private string[] ParseTLzFilter(GSP.TLzCustomExpression filter) {
			if (filter.oper == gudusoft.gsqlparser.TLzOpType.Expr_NOT) {
				string[] expParts = ParseTLzFilter((GSP.TLzCustomExpression)filter.rexpr);
				expParts[2] = "!" + expParts[2];
				return expParts;
			}
			string field = filter.lexpr.AsText;
			string oper = filter.oper == gudusoft.gsqlparser.TLzOpType.Expr_Comparison ? filter.opname.AsText : "";
			string expression = Regex.Match(filter.rexpr.AsText, @"\s*['%]*(?<expr>.+?)['%]*\s*$").Groups["expr"].Value;
			switch (filter.oper) {
				case gudusoft.gsqlparser.TLzOpType.Expr_NotLike:
					oper = "!"; break;
				case gudusoft.gsqlparser.TLzOpType.Expr_NotIn:
					oper = "!==";
					expression = Regex.Match(expression, @"\((.+)\)").Groups[1].Value;
					break;
				case gudusoft.gsqlparser.TLzOpType.Expr_In:
					oper = "==";
					expression = Regex.Match(expression, @"\((.+)\)").Groups[1].Value;
					break;
				case gudusoft.gsqlparser.TLzOpType.Expr_NotBetween:
					oper = "!><";
					expression = Regex.Match(filter.rexpr.AsText, @"\s*(?<expr>.+?)\s*$").Groups["expr"].Value;
					break;
				case gudusoft.gsqlparser.TLzOpType.Expr_Between:
					oper = "><";
					expression = Regex.Match(filter.rexpr.AsText, @"\s*(?<expr>.+?)\s*$").Groups["expr"].Value;
					break;
			}
			return new string[]{field,oper,expression};
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Sets a filter boxes. </summary>
		///
		/// <param name="filters">	The filters. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public void SetFilterBoxes(string filters) {
			Hashtable filterBoxes = new Hashtable();
			GSP.TGSqlParser sp = new GSP.TGSqlParser(GSP.TDbVendor.DbVMssql);
			sp.SqlText.Text = "SELECT * FROM T WHERE 1=1 AND "+filters;
			sp.Parse();
			List<GSP.TLzCustomExpression> lstWheres = new List<GSP.TLzCustomExpression>();
			GSP.TLzCustomExpression rExp = sp.SqlStatements[0].WhereClause as GSP.TLzCustomExpression;
			for (; rExp != null && ((GSP.TLzCustomExpression)rExp.rexpr).rexpr != null; rExp = rExp.lexpr as GSP.TLzCustomExpression)
				lstWheres.Add((GSP.TLzCustomExpression)rExp.rexpr);
			
			foreach (GSP.TLzCustomExpression filter in lstWheres){// Regex.Split(filters, " AND "))
				string[] expParts = ParseTLzFilter(filter);
				filterBoxes.Add(expParts[0], expParts[1] + expParts[2]);
			}
			GridViewEx.SetFilterBoxes(filterBoxes);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for data bound events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_DataBound(object sender, EventArgs e) {
			SetFilterBoxes(SelectFilter);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Raises the pre render event. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="e">	Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected override void OnPreRender(EventArgs e) {
			base.OnPreRender(e);
			if(SelectFilter != "" && Config.UI.DebugMode) {
				this.GridViewEx.Caption = "Filter:<font color='navy'>" + SelectFilter + "</font>";
				this.GridViewEx.CaptionAlign = TableCaptionAlign.Left;
			}
		}
		#endregion

		#region Event Handlers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Grid view ex search changed. </summary>
		///
		/// <param name="search">	The search. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_SearchChanged(string search) {
			SelectFilter = search;
			if (SearchChanged != null) SearchChanged(search);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for page index changing events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_PageIndexChanging(object sender, GridViewPageEventArgs e) {
			GridViewEx.SelectedIndex = -1;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Executes the row created action. </summary>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected virtual void OnRowCreated(object sender, GridViewRowEventArgs e) {
			if(RowCreated != null) RowCreated(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for row updated events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_RowUpdated(object sender, GridViewUpdatedEventArgs e) {
			if(RowUpdated != null) RowUpdated(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for row updating events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_RowUpdating(object sender, GridViewUpdateEventArgs e) {
			if (RowUpdating != null) RowUpdating(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for row editing ex events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_RowEditingEx(object sender, GridViewExEditEventArgs e) {
			if(RowEditingEx != null) RowEditingEx(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for row deleting events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_RowDeleting(object sender, GridViewDeleteEventArgs e) {
			if (RowDeleting != null) RowDeleting(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for row deleted events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_RowDeleted(object sender, GridViewDeletedEventArgs e) {
			if(RowDeleted != null) RowDeleted(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Executes the row inserting action. </summary>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected virtual void OnRowInserting(object sender, GridViewInsertEventArgs e) {
			if(RowInserting != null) RowInserting(sender, e);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Executes the row inserted action. </summary>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		protected virtual void OnRowInserted(object sender, GridViewInsertEventArgs e) {
			if(RowInserted != null) RowInserted(sender, e);
			if(e.Cancel) return;
			SelectedDataKey = new DataKey(e.Keys);
		}

		public bool BypassSelectException = false;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by ObjectDS for selecting events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void ObjectDS_Selecting(object sender,ObjectDataSourceSelectingEventArgs e) {
			if(DataSourceSelecting == null) return;
			DataSourceSelecting(this,new GridViewDataSourceSelectingEventArgs(e));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by ObjectDS for selected events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="SmartException">	Thrown when smart. </exception>
		/// <exception cref="InnerException">	Thrown when inner. </exception>
		/// <exception cref="Exception">			Thrown when exception. </exception>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void ObjectDS_Selected(object sender,ObjectDataSourceStatusEventArgs e) {
			try {
				if (e.Exception != null) {
					if (BypassSelectException) return;
					TargetInvocationException tie = e.Exception as TargetInvocationException;
					if (tie == null) return;
					e.ExceptionHandled = true;
					SmartException se = new SmartException(tie.InnerException);
					if (Config.UI.DebugMode) throw se;
					else throw tie.InnerException;
				}
				DataView dv = e.ReturnValue as DataView;
				if (GridViewEx.HasDataKeys && GridViewEx.SelectedDataKey != null) {
					if (dv.Count < 2) return;
					IOrderedDictionary dataKey = GridViewEx.SelectedDataKey.Values;
					dv.Sort = GridViewEx.SortExpression;
					for (int rowIndex = 0; rowIndex < dv.Count; rowIndex++) {
						DataRowView rowView = dv[rowIndex];
						int keyIndex = 0;
						foreach (string key in dataKey.Keys)
							if (dataKey[key].ToString() != rowView[key].ToString()) break;
							else keyIndex++;
						if (keyIndex == dataKey.Count) {
							GridViewEx.PageIndex = rowIndex / GridViewEx.PageSize;
							GridViewEx.SelectedIndex = rowIndex % GridViewEx.PageSize;
							break;
						}
					}
				}// else SelectedDataRowView = SelectedIndex < 0 ? null : dv[SelectedIndex + GridViewEx.PageIndex * GridViewEx.PageSize];
				if (DataSourceSelected != null) {
					DataRow[] drs = dv.Table.Select();
					if (_selectedIndexChanged || SelectedIndex >= 0) {
						List<string> lstWhere = new List<string>();
						foreach (string key in GridViewEx.DataKeyNames)
							if (GridViewEx.SelectedValues[key] + "" != string.Empty)
								lstWhere.Add(key + "='" + GridViewEx.SelectedValues[key] + "'");
						drs = dv.Table.Select(string.Join(" AND ", lstWhere.ToArray()));
					}
					DataSourceSelected(GridViewEx, new GridViewDataSourceSelectedEventArgs(drs, GridViewEx.SelectedIndex, dv, GridViewEx.PageIndex * GridViewEx.PageSize + GridViewEx.SelectedIndex));
				}
			} catch (Exception exc) {
				throw exc;
			}
		}
		private bool _selectedIndexChanged = false;

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Event handler. Called by GridViewEx for selected index changed events. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="sender">	Source of the event. </param>
		/// <param name="e">			Event information to send to registered event handlers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		void GridViewEx_SelectedIndexChanged(object sender,EventArgs e) {
			_selectedIndexChanged = true;
			if(RowSelected == null)return;
			if( GridViewEx.EditIndex >= 0 )
				RowSelected(GridViewEx,new GridViewExEventArgs(GridViewEx.EditKeys,GridViewEx.EditValues,GridViewEx.EditIndex,true));
			else
				RowSelected(GridViewEx,new GridViewExEventArgs(
					!GridViewEx.HasDataKeys || GridViewEx.SelectedDataKey==null?new OrderedDictionary():GridViewEx.SelectedDataKey.Values,
					GridViewEx.SelectedValues,GridViewEx.SelectedIndex));
		}
		#endregion

		#region Helpers

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Sets a select filter. </summary>
		///
		/// <param name="filter">	The filter. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void SetSelectFilter(string filter) {
			SelectFilter = filter;
			SetSelectFilter();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Sets a select filter. </summary>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void SetSelectFilter() {
			if(ObjectDS != null) {
				ObjectDS.Where.Clear();
				ObjectDS.Where.Add(SelectFilter);
			}
		}
		#endregion

	}

	#region FilterChangedArgs Class

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Arguments for filter changed. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class FilterChangedArgs :EventArgs {
		public readonly object SelectedValue;
		public FilterChangedArgs(object selectedValue) {
			SelectedValue = selectedValue;
		}
	}
	#endregion
}